package main

import (
	"fmt"
	"gitee.com/yuanzui/go-heimdall/circuit_breaker"
	"gitee.com/yuanzui/go-heimdall/middleware"
	"github.com/alibaba/sentinel-golang/core/circuitbreaker"
	"github.com/gin-gonic/gin"
	"math/rand"
	"net/http"
	"time"
)

const (
	TestSentinelLimit           = "/testSentinelLimit"
	TestSentinelCircuitBreaker1 = "/testSentinelCircuitBreaker1"
	TestSentinelCircuitBreaker2 = "/testSentinelCircuitBreaker2"
	TestSentinelCircuitBreaker3 = "/testSentinelCircuitBreaker3"
)

func main() {
	initRouter()
	fmt.Println("hello heimdall")
}

func initRouter() {
	// 初始化熔断器配置
	circuit_breaker.InitSentinel()
	circuit_breaker.InitSentinelLimitFlowRule(fmt.Sprintf("/limit%s", TestSentinelLimit), 3, 1000)
	circuit_breaker.InitSentinelCbFlowRule(assemblyRule())

	// 启动http服务
	router := gin.Default()
	limitRoute := router.Group("/limit").Use(middleware.SentinelCheck)
	limitRoute.GET(TestSentinelLimit, func(context *gin.Context) {
		context.String(http.StatusOK, "Hello World 没有限流!")
	})

	circuitBreakerRoute := router.Group("/circuitBreaker").Use(middleware.SentinelCheck)
	circuitBreakerRoute.GET(TestSentinelCircuitBreaker1, func(context *gin.Context) {
		time.Sleep(100 * time.Millisecond)
		context.String(http.StatusOK, "Hello World 没有慢调用熔断!")
	})
	circuitBreakerRoute.GET(TestSentinelCircuitBreaker2, func(context *gin.Context) {
		time.Sleep(100 * time.Millisecond)
		rand.Seed(time.Now().UnixNano())
		randNum := rand.Intn(100)
		if randNum%2 == 0 {
			context.String(http.StatusServiceUnavailable, "Hello World 错误!")
		} else {
			context.String(http.StatusOK, "Hello World 没有错误!")
		}
	})
	circuitBreakerRoute.GET(TestSentinelCircuitBreaker3, func(context *gin.Context) {
		time.Sleep(100 * time.Millisecond)
		context.String(http.StatusServiceUnavailable, "Hello World 没有错误计数熔断!")
	})

	err := router.Run(":4041")
	if err != nil {
		panic(fmt.Sprintf("http 服务器启动失败 => [%+v]", err))
	}
}

func assemblyRule() []*circuitbreaker.Rule {
	resp := []*circuitbreaker.Rule{
		// 慢调用比例规则（5s内有超过10%的请求响应时间超过20ms，则熔断）
		{
			Resource:         fmt.Sprintf("/circuitBreaker%s", TestSentinelCircuitBreaker1),
			Strategy:         circuitbreaker.SlowRequestRatio,
			RetryTimeoutMs:   1000,
			MinRequestAmount: 10,
			StatIntervalMs:   5000,
			MaxAllowedRtMs:   20, // 允许的最大响应时间（ms）
			Threshold:        0.1,
		},
		// 错误比例规则（5s内有超过20%的请求失败，则熔断）
		{
			Resource:         fmt.Sprintf("/circuitBreaker%s", TestSentinelCircuitBreaker2),
			Strategy:         circuitbreaker.ErrorRatio,
			RetryTimeoutMs:   2000,
			MinRequestAmount: 10,
			StatIntervalMs:   5000,
			Threshold:        0.2,
		},
		// 错误计数规则（5s内超过20个请求异常，则熔断）
		{
			Resource:         fmt.Sprintf("/circuitBreaker%s", TestSentinelCircuitBreaker3),
			Strategy:         circuitbreaker.ErrorCount,
			RetryTimeoutMs:   3000,
			MinRequestAmount: 10,
			StatIntervalMs:   5000,
			Threshold:        20,
		},
	}
	return resp
}
